
from atct_time_method import AtctTimeMethod

import logging

logging.basicConfig(level = logging.INFO,format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s')

logger = logging.getLogger(__name__)

class CommandParse:

    def __init__(self, command) -> None:
        
        self.command = command

        self.header_dict = self.header_parse()

        self.parse_result = self.get_parse_result() # 解析结果

    def header_parse(self): # 头部解析

        # 命令类型解析
        type_raw = int(self.command[8:10], 16)

        if type_raw == 0:

            command_type = "sensor_info" # 传感器日常数据

        elif type_raw == int("10", 16):

            command_type = "reporting_cycle"

        elif type_raw == int("12", 16):

            command_type = "sensor_light"

        else:

            logger.error(f"非法命令: 无法解析命令类型: {self.command}")

            command_type = None


        # 传感器类型
        if self.command[30:32] == '00':

            dev_type = "倾角"

        elif self.command[30:32] == "01":

            dev_type = "压力"

        else:

            logger.error(f"非法命令:无法解析设备类型: {self.command}")

            dev_type = None
        
        return {
            "start_character": self.command[:2],
            "len": int(self.command[2:4], 16),
            "sn": int(self.command[4:8], 16),
            "command_type": command_type,
            "devaddr": int(self.command[10:14], 16),
            "date": AtctTimeMethod(self.command[14: 30]).parse_date(),
            "dev_type": dev_type
        }


    def senor_info_parse(self): # 日常数据解释
        '''
        e51d0000000001 0021010012180908 0000000000000000000201074d9d

        e5 起如符
        1d 数据长度
        0000 sn
        00 类型
        0001 传感器地址
        00 21 01 00 12 18 09 08 RTC时间
        00 设备类型
        00000000 传感器值
        00 电量百分比
        00 指示灯光
        00 固件版本
        00 硬件版本
        02 异常数量
        01 07 两个异常值
        28 BC CRC

        '''

        if self.command[48:50] == "00":

            banormals = ""

        else:

            number_of_abnormal = int(self.command[48:50], 16)

            banormals = self.command[50: 50 + (number_of_abnormal*2)]

        if self.header_dict["dev_type"] == "倾角":
            
            sensor_value = {
                "front_and_rear_pitch_angle": self.hex_to_degrees(self.command[32: 36]), # 前后俯仰
                "left_and_right_tilt_angle": self.hex_to_degrees(self.command[36: 40]) # 左右倾斜
                
            }


        elif self.header_dict["dev_type"] == "压力":
            
            sensor_value = {"pressure_value ": self.hex_to_degrees(self.command[32: 40])}

        else:

            sensor_value =  self.command[32: 40]





        data = {

            "sensor_value": sensor_value,
            "battery_percentage": f"{int(self.command[40:42], 16)} %",
            "sensor_light": self.command[42:44],
            "firmware_version": self.command[44:46],
            "hardware_version": self.command[46:48],
            "number_of_abnormal": self.command[48:50],
            "abnormals": banormals

        }

        return data
    
    def call_back_info_parse(self):
        '''回调命令解析
        e5 24 0000 10 0001 0021010012180908 01 06 00000000 00 0000
        e5 起如符
        1d 数据长度
        0000 sn
        00 类型
        0001 传感器地址
        0021010012180908 时间
        01 00表示倾角01表示压力

        06 写入
        00000000 传感器值
        00 异常值 00表示 无异常 其它值表示有异常
        0000 crc

        '''

        data = {
            "fun": self.command[32:34],
            "value": int(self.command[34:42], 16),
            "abnormal": self.command[42:44],
        }

        return data
    
    def get_parse_result(self):

        result = self.header_dict

        if result.get("command_type") == "sensor_info":

            result.update(self.senor_info_parse())

        else:

            result.update(self.call_back_info_parse())

        return result

    @staticmethod
    def hex_to_degrees(hex_value="8113"):
        '''
        >>> hex_to_degrees("8113")
        >>> -27.5
        
        '''
        binary_value = bin(int(hex_value, 16))[2:].zfill(16)  # 将十六进制转换为二进制，并填充到16位
        sign = -1 if binary_value[0] == '1' else 1  # 判断符号位
        angle_value = int(binary_value[1:], 2)  # 将除去符号位的二进制转换为十进制
        degrees = sign * (angle_value / 10)  # 计算角度值
        return degrees

        



if __name__ == "__main__":

    # cp = CommandParse("e5 1d 0000 00 0002 0021010012180908 01  00000009 00 00 00 00 02 0107 4307".replace(' ', ''))
    # cp = CommandParse("E5 18 0000 12 0001 0021010012180908 01 06 00000001 00 5921".replace(' ', '')) # 灯
    # cp = CommandParse("E5 18 0000 10 0001 0021010012180908 01 06 00000064 00 D3C9".replace(' ', '')) # 周期回调
    # cp = CommandParse("e5 1b 0000 00 1402 24630307140000 00 811300796400010100001f75".replace(' ', '')) # 
    cp = CommandParse("e5 1b 0000 00 2205 2463030714000001 00 001020640001010000247b".replace(' ', '')) # 

    

    # cp = e51b00000014022463030714000000811300796400010100001f75

    print(cp.parse_result) # 解析结果

    print(cp.hex_to_degrees("0079"))



